package com.gobang.modules.game;

import cn.hutool.core.util.IdUtil;
import com.gobang.proto.GameProto.*;
import com.gobang.modules.record.GameRecordService;
import com.gobang.modules.message.MessageService;
import com.gobang.modules.room.Room;
import com.gobang.modules.room.RoomService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 游戏业务服务
 */
@Slf4j
@Service
public class GameService {

    @Autowired
    private MessageService messageService;
    @Autowired
    private GameRecordService gameRecordService;
    @Autowired
    private RoomService roomService;

    // 注意：现在游戏逻辑都在 Room 中，GameService 主要负责协调

    /**
     * 创建游戏房间
     */
    public Room createGame(Long blackPlayerId, String blackPlayerName,
                          Long whitePlayerId, String whitePlayerName) {
        Room room = roomService.createRoom(blackPlayerId, blackPlayerName,
                                          whitePlayerId, whitePlayerName);
        
        log.info("创建游戏房间: roomId={}, 黑方={}, 白方={}", 
                room.getRoomId(), blackPlayerName, whitePlayerName);
        
        return room;
    }
    
    /**
     * 获取房间
     */
    public Room getRoom(String roomId) {
        return roomService.getRoom(roomId);
    }
    
    /**
     * 获取玩家所在的房间
     */
    public Room getPlayerRoom(Long playerId) {
        return roomService.getPlayerRoom(playerId);
    }

    /**
     * 验证玩家是否在指定房间中
     */
    public boolean validatePlayerInRoom(Long playerId, String roomId) {
        if (playerId == null || roomId == null) {
            return false;
        }
        Room room = roomService.getPlayerRoom(playerId);
        return room != null && roomId.equals(room.getRoomId());
    }

    /**
     * 获取玩家所在的房间ID
     */
    public String getPlayerRoomId(Long playerId) {
        return roomService.getPlayerRoomId(playerId);
    }

    /**
     * 处理落子请求
     * 使用服务器权威的 roomId 和 userId
     */
    public void handlePlacePiece(String roomId, Long userId, int row, int col) {
        PlacePieceResponse response = placePiece(roomId, userId, row, col);

        // 发送给双方玩家
        Room room = getRoom(roomId);
        if (room != null) {
            messageService.sendToPlayer(room.getBlackPlayerId(), MessageType.PLACE_PIECE_RESPONSE, response.toByteArray());
            messageService.sendToPlayer(room.getWhitePlayerId(), MessageType.PLACE_PIECE_RESPONSE, response.toByteArray());

            // 检查游戏是否结束
            if (room.isGameOver()) {
                handleGameOver(room);
            }
        }
    }

    /**
     * 落子
     */
    private PlacePieceResponse placePiece(String roomId, Long userId, int row, int col) {
        Room room = getRoom(roomId);
        if (room == null) {
            return PlacePieceResponse.newBuilder()
                    .setSuccess(false)
                    .setMessage("房间不存在")
                    .build();
        }
        
        if (room.isGameOver()) {
            return PlacePieceResponse.newBuilder()
                    .setSuccess(false)
                    .setMessage("游戏已结束")
                    .build();
        }
        
        boolean success = room.placePiece(row, col, userId);
        
        if (!success) {
            return PlacePieceResponse.newBuilder()
                    .setSuccess(false)
                    .setMessage("落子失败")
                    .build();
        }
        
        PlacePieceResponse.Builder builder = PlacePieceResponse.newBuilder()
                .setSuccess(true)
                .setMessage("落子成功")
                .setRow(row)
                .setCol(col)
                .setColor(room.getPlayerColor(userId));
        
        if (!room.isGameOver()) {
            builder.setNextTurn(room.getCurrentTurn())
                   .setNextPlayerId(room.getCurrentPlayerId());
        }
        
        return builder.build();
    }

    /**
     * 处理投降请求
     */
    public void handleSurrender(String roomId, Long playerId) {
        surrender(roomId, playerId);

        Room room = getRoom(roomId);
        if (room != null && room.isGameOver()) {
            handleGameOver(room);
        }
    }

    /**
     * 投降
     */
    private void surrender(String roomId, Long playerId) {
        Room room = getRoom(roomId);
        if (room != null && !room.isGameOver()) {
            room.surrender(playerId);
            log.info("玩家投降: roomId={}, playerId={}", roomId, playerId);
        }
    }

    /**
     * 处理玩家断线
     */
    public void handlePlayerDisconnect(Long userId) {
        Room room = getPlayerRoom(userId);
        if (room != null && !room.isGameOver()) {
            // 玩家断线视为投降
            room.surrender(userId);
            roomService.endGame(room.getRoomId());
        }
    }

    /**
     * 移除房间
     */
    private void removeRoom(String roomId) {
        roomService.removeRoom(roomId);
        log.info("移除房间: roomId={}", roomId);
    }

    /**
     * 处理游戏结束
     * 发送 GameOverSync 同步消息通知所有玩家
     */
    private void handleGameOver(Room room) {
        // 结束房间游戏
        roomService.endGame(room.getRoomId());
        
        // 保存游戏记录
        gameRecordService.saveGameRecord(room);

        // 发送游戏结束同步消息
        GameOverSync gameOverSync = GameOverSync.newBuilder()
                .setGameId(room.getGameId())
                .setResult(room.getResult())
                .setWinnerId(room.getWinnerId() != null ? room.getWinnerId() : 0)
                .setWinnerName(getWinnerName(room))
                .addAllWinPositions(room.getWinPositions())
                .build();

        messageService.sendToPlayer(room.getBlackPlayerId(), MessageType.GAME_OVER_SYNC, gameOverSync.toByteArray());
        messageService.sendToPlayer(room.getWhitePlayerId(), MessageType.GAME_OVER_SYNC, gameOverSync.toByteArray());

        // 移除房间
        removeRoom(room.getRoomId());

        log.info("游戏结束: roomId={}, result={}, winner={}", 
                room.getRoomId(), room.getResult(), getWinnerName(room));
    }

    /**
     * 获取胜者名称
     */
    private String getWinnerName(Room room) {
        if (room.getWinnerId() == null) {
            return "";
        }
        if (room.getWinnerId().equals(room.getBlackPlayerId())) {
            return room.getBlackPlayerName();
        }
        return room.getWhitePlayerName();
    }
}
